//
// AddressSpace.cpp
// Usage: Manage user address space
// CreateDate: 2009-05-03
// Author: MaJiuyue
//
#include "AddressSpace.h"
#include "../schedule/Process.h"

AddressSpace::AddressSpace(addr_t HeapStart, addr_t StackBase)
	: m_HeapStart(HeapStart), m_StackBase(StackBase)
{
	m_HeapEnd = HeapStart;
	m_StackTop = m_StackBase - PAGE_SIZE;
}

AddressSpace::AddressSpace(const AddressSpace &target)
{
	m_HeapStart = target.m_HeapStart;
	m_HeapEnd = target.m_HeapEnd;
	m_StackBase = target.m_StackBase;
	m_StackTop = target.m_StackTop;
}

AddressSpace::~AddressSpace()
{
}

addr_t AddressSpace::ExtendHeap(int incr)
{
	addr_t m_PrevHeapEnd = m_HeapEnd;

//kprintf("KNL: Process %d ExtendHeap(0x%x)\n", GetCurrentProcess()->GetPID(),incr);
	// Do check
	if(m_HeapEnd+incr<m_HeapStart || m_HeapEnd+incr>m_StackTop)
		panic("User heap overflow!");

	// Do resize
	m_HeapEnd += incr;

	return m_PrevHeapEnd;
}

void AddressSpace::ExtendStack(int incr)
{
	incr = (incr+PAGE_SIZE-1) & 0xFFFFF000;

	// Do check
	if(m_StackTop+incr>m_StackBase || m_StackTop+incr<m_HeapEnd)
		panic("User stack overflow!");	

	// Do resize
	m_StackTop -= incr;
}

bool AddressSpace::IsContain(addr_t addr)
{
	if(addr >= m_StackBase)
		return false;

	if(addr<m_HeapStart)
		return false;

	if(addr>=m_HeapEnd && addr<m_StackTop-10*PAGE_SIZE)
		return false;

	// Resize stack
	if(addr>=m_HeapEnd && addr<m_StackTop)
		m_StackTop = addr&0xFFFFF000 + 10*PAGE_SIZE;

	return true;
}

addr_t AddressSpace::AllocUser(size_t size)
{
	return m_StackBase+PAGE_SIZE;
}
void AddressSpace::DeallocUser(addr_t vaddr, size_t size)
{

}
